﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SocketLib
{
	/// <summary>
	/// 固定区
	/// </summary>
	public class Root
	{
		/*
		 * 固定区-38
		 * 包版本-2
		 * 包类型-1
		 * 可变区长度-2
		 * 可变区Hash码-32
		 * 可变区是否加密-1
		 */
		private byte[] _version = new byte[32];//包版本(标识符)
		private byte _type = BasePackage.Extends_None;//包类型
		private byte[] _pieceLeng = new byte[2];//可变区长度
		private byte[] _pieceHash = new byte[32];//可变区Hash码
		private bool _dynamicLock = true;//可变区是否被加密

		internal Root() { }
		/// <summary>
		/// 包版本  [R/W]
		/// </summary>
		public string PackageVersion
		{
			get { return System.Text.UTF8Encoding.UTF8.GetString(_version).Split('\0')[0]; }
			set { _version = System.Text.UTF8Encoding.UTF8.GetBytes(value); }
		}
		/// <summary>
		/// 包类型  [R/W]
		/// </summary>
		public byte Type
		{
			get { return _type; }
			set { _type = value; }
		}
		/// <summary>
		/// 可变区长度  [R/W]
		/// </summary>
		public UInt16 PieceLeng
		{
			get { return BitConverter.ToUInt16(_pieceLeng, 0); }
			set { _pieceLeng = BitConverter.GetBytes(value); }
		}
		/// <summary>
		/// 可变区Hash码  [R/W]
		/// </summary>
		public string PieceHash
		{
			get { return UTF8Encoding.ASCII.GetString(_pieceHash); }
			set
			{
				if (value.Length == 32)
					_pieceHash = UTF8Encoding.ASCII.GetBytes(value);
				else
					//throw new HashLengthException("PieceHash应为32长度的字节数组");
					throw new Exception("PieceHash应为32长度的字节数组");
			}
		}
		/// <summary>
		/// 可变区是否被加密  [R/W]
		/// </summary>
		public bool DynamicLock
		{
			get { return _dynamicLock; }
			set { _dynamicLock = value; }
		}
		/// <summary>
		/// 获得该数据片，返回38长度的字节数组
		/// </summary>
		/// <returns>返回数据片</returns>
		internal byte[] GetPiece()
		{
			byte[] returnData = new byte[68];//38个长度的固定区

			_version.CopyTo(returnData, 0);
			returnData[32] = _type;
			_pieceLeng.CopyTo(returnData, 33);
			_pieceHash.CopyTo(returnData, 35);
			returnData[67] = BitConverter.GetBytes(_dynamicLock)[0];

			return returnData;
		}
		/// <summary>
		/// 设置数据到可变换区
		/// </summary>
		/// <param name="value">要设置的数据</param>
		internal void SetPiece(byte[] value)
		{
			if (value.Length != 68)
				//throw new DataLengthException();//数据长度错误
				throw new Exception();
			Buffer.BlockCopy(value, 0, _version, 0, 32);//包版本-32
			_type = value[32];//包类型-1
			Buffer.BlockCopy(value, 33, _pieceLeng, 0, 2);//可变区长度-2
			Buffer.BlockCopy(value, 35, _pieceHash, 0, 32);//可变区Hash码-32
			_dynamicLock = BitConverter.ToBoolean(value, 67);
		}
	}

	/// <summary>
	/// 可变区数据块
	/// </summary>
	public class Variety
	{
		/*
		 * 可变区-108
		 * 
		 * 客户Session码-32
		 * 使用的管道号-1
		 * 片编号-4
		 * 片大小-4
		 * 片校验码256位-32
		 * 片是否被加密-1
		 * 尾段长度-4
		 * 尾段Hash码-32
		 */
		private byte[] _SessionString = new byte[32];//客户Session
		private byte[] _number = new byte[4];//片编号
		private byte[] _dataLen = new byte[4];//数据总大小(真实)
		private byte[] _pieceLeng = new byte[4];//片长度(网络包中)
		private byte[] _dataHash = new byte[32];//片Hash码
		private bool _varietyeLock = true;//片是否被加密
		private byte[] _offalLeng = new byte[4];//尾段长度
		private byte[] _offalHash = new byte[32];//尾段Hash码

		internal Variety() { }
		/// <summary>
		/// 客户Session码-32字节  [R/W]
		/// </summary>
		public string Session
		{
			get { return UTF8Encoding.ASCII.GetString(_SessionString); }
			set
			{
				if (value.Length == 32)
					_SessionString = UTF8Encoding.ASCII.GetBytes(value);
				else
					//throw new SessionLengthException();//Session应为32长度的字节数组
					throw new Exception();
			}
		}

		/// <summary>
		/// 片编号-4字节  [R/W]
		/// </summary>
		public int Number
		{
			get { return BitConverter.ToInt32(_number, 0); }
			set { _number = BitConverter.GetBytes(value); }
		}
		/// <summary>
		/// 在网络上传输的数据真实长度  [R/W]
		/// </summary>
		public int DataLenth
		{
			get { return BitConverter.ToInt32(_dataLen, 0); }
			set { _dataLen = BitConverter.GetBytes(value); }
		}
		/// <summary>
		/// 数据片长度  [R/W]
		/// </summary>
		public int PieceLeng
		{
			get { return BitConverter.ToInt32(_pieceLeng, 0); }
			set { _pieceLeng = BitConverter.GetBytes(value); }
		}
		/// <summary>
		/// 数据区Hash码  [R/W]
		/// </summary>
		public string DataHash
		{
			get { return UTF8Encoding.ASCII.GetString(_dataHash); }
			set
			{
				if (value.Length == 32)
					_dataHash = UTF8Encoding.ASCII.GetBytes(value);
				else
					//throw new HashLengthException("DataHash应为32长度的字节数组");
					throw new Exception();

			}
		}
		/// <summary>
		/// 片是否被加密  [R/W]
		/// </summary>
		public bool VarietyeLock
		{
			get { return _varietyeLock; }
			set { _varietyeLock = value; }
		}
		/// <summary>
		/// 尾段长度  [R/W]
		/// </summary>
		public int OffalLeng
		{
			get { return BitConverter.ToInt32(_offalLeng, 0); }
			set { _offalLeng = BitConverter.GetBytes(value); }
		}
		/// <summary>
		/// 尾段Hash码  [R/W]
		/// </summary>
		public string OffalHash
		{
			get { return UTF8Encoding.ASCII.GetString(_offalHash); }
			set
			{
				if (value.Length == 32)
					_offalHash = UTF8Encoding.ASCII.GetBytes(value);
				else
					//throw new HashLengthException("OffalHash应为32长度的字节数组");
					throw new Exception();

			}
		}
		/// <summary>
		/// 获得该数据片，返回110长度的字节数组
		/// </summary>
		/// <returns>返回数据片</returns>
		internal byte[] GetPiece()
		{
			byte[] returnData = new byte[114];//110个长度的可变区

			_SessionString.CopyTo(returnData, 0);//客户Session码-32
			//returnData[32] = _Conduit;//使用的管道号-1
			_number.CopyTo(returnData, 32);//片编号-4
			_dataLen.CopyTo(returnData, 36);//数据总长度-4
			_pieceLeng.CopyTo(returnData, 40);//片大小-4
			_dataHash.CopyTo(returnData, 44);//数据区校验码256位-32
			returnData[76] = Convert.ToByte(_varietyeLock);//片是否被加密-1
			_offalLeng.CopyTo(returnData, 77);//尾段长度-4
			_offalHash.CopyTo(returnData, 81);//尾段Hash码256位-32

			return returnData;
		}
		/// <summary>
		/// 设置数据到可变换区
		/// </summary>
		/// <param name="value">可变区数据</param>
		internal void SetPiece(byte[] value)
		{
			if (value.Length < 114)
				//throw new DataLengthException();//数据长度错误
				throw new Exception();


			Buffer.BlockCopy(value, 0, _SessionString, 0, 32);//客户Session码-32
			//_Conduit = value[32];//使用的管道号-1
			Buffer.BlockCopy(value, 32, _number, 0, 4);//片编号-4
			Buffer.BlockCopy(value, 36, _dataLen, 0, 4);//数据总长度-4
			Buffer.BlockCopy(value, 40, _pieceLeng, 0, 4);//片大小-4
			Buffer.BlockCopy(value, 44, _dataHash, 0, 32);//数据区校验码256位-32
			_varietyeLock = Convert.ToBoolean(value[76]);//片是否被加密-1
			Buffer.BlockCopy(value, 77, _offalLeng, 0, 4);//尾段长度-4
			Buffer.BlockCopy(value, 81, _offalHash, 0, 32);//尾段Hash码256位-32
		}
	}
}

